package org.example.compress;

import java.io.File;
import java.io.IOException;
import java.util.Objects;

/**
 * 通过调用本地系统的7z压缩工具，对文件进行解、压缩
 */
public class CompressBy7z {


    public static void runLocalCommand(String localCommand, String[] envp, File dir) throws InterruptedException, IOException {
        Process process = Runtime.getRuntime().exec(localCommand, envp, dir);
        // 监听出错信息
        CompressBy7zCache errorGobbler = new CompressBy7zCache(process.getErrorStream(), "ERROR");

        // 监听输出信息
        CompressBy7zCache outputGobbler = new CompressBy7zCache(process.getInputStream(), "OUTPUT");

        // 启动监听输入
        errorGobbler.start();
        outputGobbler.start();

        // 确保 Runtime.exec 进程运行完成
        int exitVal = process.waitFor();
        System.out.println("ExitValue: " + exitVal);
    }

    /**
     * cmd 7z 解压
     *
     * @param zipFileName a
     * @param outputDir   输出目录
     * @param zipToolPath 本地7-Zip软件的安装路径
     * @return 返回命令执行状态
     */
    public static int unzip(String zipFileName, String outputDir, String zipToolPath) throws InterruptedException, IOException {
        String[] cmd = {
                zipToolPath,
                "x",//x:完整路径下解压文件
                "-y",//-y:所有确认选项都默认为是(即不出现确认提示)
                "-aos", // 跳过已存在的文件
                zipFileName,//D:\test\测试文件.zip"-x!*MSS*",
                "-o" + outputDir//-o:设置输出目录，D:\test
        };
        Process process = Runtime.getRuntime().exec(cmd);
        // 监听出错信息
        CompressBy7zCache errorGobbler = new CompressBy7zCache(process.getErrorStream(), "ERROR");

        // 监听输出信息
        CompressBy7zCache outputGobbler = new CompressBy7zCache(process.getInputStream(), "OUTPUT");

        // 启动监听输入
        errorGobbler.start();
        outputGobbler.start();

        // 确保 Runtime.exec 进程运行完成
        int exitVal = process.waitFor();
        System.out.println("ExitValue: " + exitVal);
        return exitVal;
    }

    /**
     * 生成.toZip压缩文件
     *
     * @param workspace   需要压缩的文件所在的父目录
     * @param zipFileName 生成压缩文件的文件名（全路径）
     * @param commandPath 本地7-Zip软件的安装路径
     */
    public static void fileToZip(String inPath, String zipFileName, String commandPath, String mode, String workspace, String password) throws Exception {
        String command = password == null ? String.format(
                "%s a %s -r %s",
                commandPath, zipFileName, inPath
        ) : String.format(
                "%s a -p%s %s -r %s",
                commandPath, password, zipFileName + "-mima-" + password + ".7z", inPath
        );
        File inPathFile = new File(inPath);
        File workspaceDir = workspace != null ? new File(workspace) :
                inPathFile.isDirectory() ? inPathFile : inPathFile.getParentFile();

        if (mode.equals("dir")) {
            //inPath是目录，将目录压缩打包为一个文件
            runLocalCommand(command, null, workspaceDir);
        }
        if (mode.equals("recurse")) {
            if (inPathFile.isDirectory()) {
                int count = 0;
                for (File file : Objects.requireNonNull(inPathFile.listFiles())) {
                    String fileName = file.getName().replaceAll(" +", "-");
                    int lastIndexOfDian = fileName.lastIndexOf(".");
                    if (lastIndexOfDian > 0)
                        fileName = fileName.substring(0, lastIndexOfDian);

                    String preFilePath = file.getPath();
                    command = password == null ? String.format(
                            "%s a %s -r %s",
                            commandPath, workspaceDir.getPath() + "/" + fileName + ".7zz", preFilePath
                    ) : String.format(
                            "%s a -p%s %s %s",
                            commandPath, password, workspaceDir.getPath() + "/" + fileName + "-mima-" + password + ".7z", preFilePath
                    );
                    count += 1;
                    runLocalCommand(command, null, workspaceDir);
                    System.out.printf("第%d个文件--%s%n", count, fileName);
                }
            } else {

                if (password != null) {
                    command = String.format(
                            "%s a %s -r %s",
                            commandPath, zipFileName.replace("7z", "-mima-" + password + ".7z"), inPath
                    );
                }
                runLocalCommand(command, null, workspaceDir);
            }

        }
    }

    public static void main(String[] args) throws Exception {
        //mac test
//        String inPath = "/Users/dobbin/develop/tmp/ziptest";
//        String zipFileName = "abc.7z";
//        String commandPath = "/Users/dobbin/develop/etc/7z2300-mac/7zz";
//        String mode = "recurse";
//        String workspace = "/Users/dobbin/develop/tmp/ziptest_rsdir";
//        String password = "pwd2233";
//        fileToZip(inPath, zipFileName, commandPath, mode, workspace, password);

        //windows test
        String inPath = "D:\\develop\\tmp\\test";
        String zipFileName = "abc.7z";
        String commandPath = "D:\\develop\\bin\\7zr.exe";
        String mode = "recurse";
        String workspace = "D:\\develop\\tmp\\test";
        String password = "pwd2233";
        fileToZip(inPath, zipFileName, commandPath, mode, workspace, password);

    }
}